MapBasic - Нарисовать сектор на карте. Как?
-
- Интересующийся
- Сообщения: 39
- Зарегистрирован: 28 янв 2015, 22:07
- Репутация: 1
- Откуда: Воронеж
MapBasic - Нарисовать сектор на карте. Как?
Добрый день, коллеги!
Может кто сталкивался, и сможет подсказать, как лучше реализовать рисование сектора на карте.
Дано: координаты центра, азимут(основное направление в градусах), ширина сектора в градусах и радиус.
Необходимо на карте изобразить область соотвествующую данному сектору.
Могу нарисовать линию по азимуту заданной длины, ну иди точку на окружности. Непонятно что делать с дугой.
1. вроде бы есть стандартный оператор Create Arc, но что-то не попадалось мне примеров его использования и пока не понятно можно-ли им будет воспользоваться, а также нет соответствующей ему функции.
2. существует тупой и дуболомный способ - на дуге нанести N точек и соединить линиями точки по периметру - навскидку метод явно не экономичный и по вычислениям и по размерам объекта, также непонятно сколько точек на xx градусов нужно для гладкого отображения дуги. Если число точек переменное, непонятно как реализовать структуру переменной длины для хранения переменного числа точек.
Буду благодарен если кто-то сможет что-либо подсказать по данному вопросу или поделится кусками кода.
Спасибо.
Может кто сталкивался, и сможет подсказать, как лучше реализовать рисование сектора на карте.
Дано: координаты центра, азимут(основное направление в градусах), ширина сектора в градусах и радиус.
Необходимо на карте изобразить область соотвествующую данному сектору.
Могу нарисовать линию по азимуту заданной длины, ну иди точку на окружности. Непонятно что делать с дугой.
1. вроде бы есть стандартный оператор Create Arc, но что-то не попадалось мне примеров его использования и пока не понятно можно-ли им будет воспользоваться, а также нет соответствующей ему функции.
2. существует тупой и дуболомный способ - на дуге нанести N точек и соединить линиями точки по периметру - навскидку метод явно не экономичный и по вычислениям и по размерам объекта, также непонятно сколько точек на xx градусов нужно для гладкого отображения дуги. Если число точек переменное, непонятно как реализовать структуру переменной длины для хранения переменного числа точек.
Буду благодарен если кто-то сможет что-либо подсказать по данному вопросу или поделится кусками кода.
Спасибо.
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
Оператор построения дуги имеет следующий вид
Create Arc Into Window idMap (x1,y1) (x2,y2) _start _end
Все обозначения в соответствии с рисунком.
Прилагаемый код строит сектор, все необходимые комментарии в коде.
Строится точка {x0,y0} и дуга, далее к этим объектам применяется оператор ConvexHull (возвращает выпуклую оболочку для объектов аргументов) что приводит к некоторому загрублению результата. Если требуется большая точность, то нужно непосредственно вычислить координаты точек на дуге в направлении End и Start и этих данных будет достаточно для определения искомого объекта.
Create Arc Into Window idMap (x1,y1) (x2,y2) _start _end
Все обозначения в соответствии с рисунком.
Прилагаемый код строит сектор, все необходимые комментарии в коде.
Строится точка {x0,y0} и дуга, далее к этим объектам применяется оператор ConvexHull (возвращает выпуклую оболочку для объектов аргументов) что приводит к некоторому загрублению результата. Если требуется большая точность, то нужно непосредственно вычислить координаты точек на дуге в направлении End и Start и этих данных будет достаточно для определения искомого объекта.
- Вложения
-
- sector.zip
- (877 байт) 397 скачиваний
-
- miHG127.png (4.16 КБ) 14658 просмотров
-
- Интересующийся
- Сообщения: 39
- Зарегистрирован: 28 янв 2015, 22:07
- Репутация: 1
- Откуда: Воронеж
Re: MapBasic - Нарисовать сектор на карте. Как?
Большое спасибо за пример. Пытаюсь разобраться. Пока получается не совсем то что хотелось. Дуга почему-то не круглая
- Вложения
-
- Sector_rezult1.png (5.76 КБ) 14622 просмотра
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
Изображение дуги в любом случае дискретно. Качество приближения к круговой кривой определяется оператором Set Resolution N. Кроме того нужно учитывать возможность используемой координатной системы отображать заявленную дискретность.
- Вложения
-
- miHG134.png (56.02 КБ) 14612 просмотров
-
- Интересующийся
- Сообщения: 39
- Зарегистрирован: 28 янв 2015, 22:07
- Репутация: 1
- Откуда: Воронеж
Re: MapBasic - Нарисовать сектор на карте. Как?
Попробовал все пересчитать по формулам
RZ = 6371000 'Радиус Земли в м
lat1_1 = y0 + 300*cos(Azimut*PI/180)/(RZ*PI/180)
lon1_1 = x0 + 300*sin(Azimut*PI/180)/cos(y0*PI/180)/(RZ*PI/180)
Стало лучше. Но все равно итоговый результат не устраивает. Видно заметное расхождение от прорисованных отрезков в заданном направлении. Непонятно, в чем причина. Такое ощущение, что приведенные выше формулы не точны. Можно-ли как-то победить наблюдаемое расхождение?
RZ = 6371000 'Радиус Земли в м
lat1_1 = y0 + 300*cos(Azimut*PI/180)/(RZ*PI/180)
lon1_1 = x0 + 300*sin(Azimut*PI/180)/cos(y0*PI/180)/(RZ*PI/180)
Стало лучше. Но все равно итоговый результат не устраивает. Видно заметное расхождение от прорисованных отрезков в заданном направлении. Непонятно, в чем причина. Такое ощущение, что приведенные выше формулы не точны. Можно-ли как-то победить наблюдаемое расхождение?
- Вложения
-
- Sector_rezult3.png (7.95 КБ) 14586 просмотров
- Игорь Белов
- Гуру
- Сообщения: 2229
- Зарегистрирован: 04 янв 2011, 22:00
- Репутация: 1501
- Откуда: Казань
Re: MapBasic - Нарисовать сектор на карте. Как?
Прямая геодезическая задача на сфере
об уравнении окружности на сфере
к расчёту координат от точки по азимуту
об уравнении окружности на сфере
к расчёту координат от точки по азимуту
The purpose of computing is insight, not numbers
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
Замените код определения координат углов покрытия (x1,y1,x2,y2). Чтобы не переходить к громоздким вычислениям на сфере, определил их косвенно исходя из возможностей МВ.
dim cir as object
R=1000 'в метрах
cir=CreateCircle(x0,y0,R)
x1=ObjectGeography(cir,OBJ_GEO_MINX)
y2=ObjectGeography(cir,OBJ_GEO_MINY)
x2=ObjectGeography(cir,OBJ_GEO_MAXX)
y1=ObjectGeography(cir,OBJ_GEO_MAXY)
Из аналогичных соображений можно получить и вектора соединяющие концы дуги с центром {x0,y0}.
dim cir as object
R=1000 'в метрах
cir=CreateCircle(x0,y0,R)
x1=ObjectGeography(cir,OBJ_GEO_MINX)
y2=ObjectGeography(cir,OBJ_GEO_MINY)
x2=ObjectGeography(cir,OBJ_GEO_MAXX)
y1=ObjectGeography(cir,OBJ_GEO_MAXY)
Из аналогичных соображений можно получить и вектора соединяющие концы дуги с центром {x0,y0}.
-
- Интересующийся
- Сообщения: 39
- Зарегистрирован: 28 янв 2015, 22:07
- Репутация: 1
- Откуда: Воронеж
Re: MapBasic - Нарисовать сектор на карте. Как?
Попробовал все-таки додавить идею с громоздкими вычислениями на сфере (т.к. вопрос важный сам по себе). В результате получилось как-то:
Осталось нерешенным несколько проблем:
1)
вызывает меню где требуется ручное вмешательство. Если нужно нарисовать 1000 секторов - это становиться неприемлемым. Можно-ли это как-то побороть или обойти?
2) После создания сектора остается дуга. По идеи ее необходимо удалить. Вопрос как?
3)Руками нарисованные линии-границы секторов немного, но не совпадают с дугой... В рамках данного подхода, если отталкиваться от необходимости руками замкнуть контур, требуется как-то их свести друг с другом. Непонятно как... (Повысить точность вычислений на сфере?? Воспользоваться какими-нибудь процедурами проверки??) Лучше бы данной процедуры избежать совсем...
В свете вышеизложенного гораздо более перспективным выглядит предложенный выше подход:
1. Построить круг
2. Средствами MapBasic получить координаты минимального описывающего прямоугольника
3. По этим координатам построить дугу
4. Превратить дугу в полилинию
5. Средствами MapBasic получить координаты концов дуги (точные!!!)
... далее пока не понятно...
6. Нарисовать две линии из центра ТОЧНО в концы дуги
7. Замкнуть контур и превратить его в область
...или
6. Добавить к полилинии дуги еще одну точку ЦЕНТР и как-то суметь превратить все это сектор???
Сейчас занимаюсь реализацией второго сценария. В общем пока вопросов больше чем ответов. Актуален вопрос с быстродействием. Непонятно, что, где и когда быстрее работает? Оператор, функция? с переменными, с таблицами, с картами и т.д.
Код: Выделить всё
define PI 3.1415926535897932384626433832795
define SQRT2 1.4142135623730950488016887242097
'Средний радиус Земли в м
define RZ 6371000
sub DrowSector_menu_func
Dim azimut, SectorWidth, r , LAT0, LON0 as float
' Данные для примера
azimut = 120 'направление центра сектора в градусах
SectorWidth = 60 'ширина сектора в градусах
r = 300 'длина сектора на местности в метрах
LON0 = 35.976
LAT0 = 56.514
'Call DrowSector(0, 60, 300 ,56.514,35.976)
Call DrowSector(azimut, SectorWidth, r , LAT0, LON0)
End Sub
sub DrowSector( ByVal azimut as float, ByVal SectorWidth as float, ByVal r as float, ByVal LAT0 as float, ByVal LON0 as float )
' система координат устанавливается по таблице
' в которой выполняется построение (WGS84)
'Set CoordSys table input_table
Set Distance Units "m"
Set Resolution 1.8*SectorWidth 'определяет точность отрисовки дуги, чем больше тем выше точность
' Для использования Create Arc потребуются дополнительные вычисления. Нужно определить
' координаты концов одной диагонали квадрата, в который может быть вписана воображаемая
' окружность того же радиуса, что и у наша дуги
dim ArcLat1, ArcLon1 as float 'координаты левого верхнего угла квадрата (azimut = 315)
dim ArcLon2, ArcLat2 as float 'координаты правого нижненго угла квадрата (azimut = 135)
' и вычислить начальный и конечный угол дуги относительно 0° (направление на восток),
' отсчитываемые против часовой стрелки
dim ArcAngleStart, ArcAngleEnd as float 'углы начала и конца дуги отсчитанные от востока
'Вычисляем координаты диагонали
Call calc_coordinats(ArcLat1, ArcLon1, r*SQRT2, 315, LAT0, LON0)
Call calc_coordinats(ArcLat2, ArcLon2, r*SQRT2, 135, LAT0, LON0)
'Вычисляем углы
ArcAngleStart = Arc_angle_convert(azimut + SectorWidth/2)
ArcAngleEnd = Arc_angle_convert(azimut - SectorWidth/2)
' -------------------------------------------------
dim idMap,n as integer
idMap = frontWindow()
dim curArc as object
dim x1,y1, x2,y2 as float
' выполняем построение на редактируемом слое (ss)
Create Point Into Window idMap (LON0,LAT0)
'рисуем дугу
Create Arc Into Window idMap (ArcLon2,ArcLat2) (ArcLon1,ArcLat1) ArcAngleStart ArcAngleEnd
'число строк в открытой таблице
n = TableInfo(input_table,TAB_INFO_NROWS)
'выбираем последние добавленные записи Point и Arc
Select * From input_table Where rowid > n-2
Run Menu Command M_OBJECTS_CONVEX_HULL
' -------------------------------------------------
' руками рисуем линии левой и правой границ сектора
dim latP1,lonP1, azimut_left as float
dim latP2,lonP2, azimut_rigth as float
azimut_left = calc_Azimut_left(azimut, SectorWidth)
Call calc_coordinats(latP1, lonP1, r, azimut_left, LAT0, LON0)
azimut_rigth = calc_Azimut_rigth(azimut, SectorWidth)
Call calc_coordinats(latP2, lonP2, r, azimut_rigth, LAT0, LON0)
Create Line Into Window idMap (LON0,LAT0) (lonP1,latP1)
Create Line Into Window idMap (LON0,LAT0) (lonP2,latP2)
End Sub
'--------------------------------------------------------------------------------------
' Пересчет азимутов для оператора Create Arc
'--------------------------------------------------------------------------------------
Function Arc_angle_convert(ByVAL azimut as float) as float
dim az as float
az = 90 - azimut
If az < 0 Then
Arc_angle_convert = 360 + az
Else
Arc_angle_convert = az
End If
End Function
'--------------------------------------------------------------------------------------
' Вычисление координаты точки расположенной на расстоянии r в направлении azimut
'--------------------------------------------------------------------------------------
Sub calc_coordinats(lat as float, lon as float, ByVal r as float, ByVal azimut as float, ByVal lat0 as float, ByVal lon0 as float )
'dim PI,RZ as float
'PI = 3.1415926535897932384626433832795
'RZ = 6371000 'Средний радиус Земли в м
lat = lat0 + r*cos(azimut*PI/180)/(RZ*PI/180)
lon = lon0 + r*sin(azimut*PI/180)/cos(lat0*PI/180)/(RZ*PI/180)
End Sub
'--------------------------------------------------------------------------------------
' Вычисление азимута левой границы сектора
'--------------------------------------------------------------------------------------
Function calc_Azimut_left(Azimut as float, SectorWidth as float) as float
Dim SectorWidth_div2 as Float
SectorWidth_div2 = SectorWidth/2
If (Azimut - SectorWidth_div2) < 0 Then
calc_Azimut_left = 360 - (SectorWidth_div2 - Azimut )
Else
calc_Azimut_left = Azimut - SectorWidth_div2
End If
End Function
'--------------------------------------------------------------------------------------
' Вычисление азимута правой границы сектора
'--------------------------------------------------------------------------------------
Function calc_Azimut_rigth(Azimut as float, SectorWidth as float) as float
Dim SectorWidth_div2 as Float
SectorWidth_div2 = SectorWidth/2
If (Azimut + SectorWidth_div2) > 360 Then
calc_Azimut_rigth = SectorWidth_div2 - (360 - Azimut )
Else
calc_Azimut_rigth = Azimut + SectorWidth_div2
End If
End Function
Осталось нерешенным несколько проблем:
1)
Код: Выделить всё
Run Menu Command M_OBJECTS_CONVEX_HULL
2) После создания сектора остается дуга. По идеи ее необходимо удалить. Вопрос как?
3)Руками нарисованные линии-границы секторов немного, но не совпадают с дугой... В рамках данного подхода, если отталкиваться от необходимости руками замкнуть контур, требуется как-то их свести друг с другом. Непонятно как... (Повысить точность вычислений на сфере?? Воспользоваться какими-нибудь процедурами проверки??) Лучше бы данной процедуры избежать совсем...
В свете вышеизложенного гораздо более перспективным выглядит предложенный выше подход:
1. Построить круг
2. Средствами MapBasic получить координаты минимального описывающего прямоугольника
3. По этим координатам построить дугу
4. Превратить дугу в полилинию
5. Средствами MapBasic получить координаты концов дуги (точные!!!)
... далее пока не понятно...
6. Нарисовать две линии из центра ТОЧНО в концы дуги
7. Замкнуть контур и превратить его в область
...или
6. Добавить к полилинии дуги еще одну точку ЦЕНТР и как-то суметь превратить все это сектор???
Сейчас занимаюсь реализацией второго сценария. В общем пока вопросов больше чем ответов. Актуален вопрос с быстродействием. Непонятно, что, где и когда быстрее работает? Оператор, функция? с переменными, с таблицами, с картами и т.д.
-
- Активный участник
- Сообщения: 216
- Зарегистрирован: 21 окт 2009, 13:29
- Репутация: 28
- Откуда: Новосибирск
Re: MapBasic - Нарисовать сектор на карте. Как?
Я думаю, проще создать дугу, превратить ее в полилинию и добавить в нее отрезки до центра. После этого можете спокойно превращать все в полигон.tems-ya писал(а): 6. Добавить к полилинии дуги еще одну точку ЦЕНТР и как-то суметь превратить все это сектор???
А в чем собственно проблема? Сколько у вас вычислений? Я считаю, пока не решите задачу и не проверите на реальных данных, думать о быстродействии рано.tems-ya писал(а): В общем пока вопросов больше чем ответов. Актуален вопрос с быстродействием. Непонятно, что, где и когда быстрее работает? Оператор, функция?
Ну и еще вопрос: какая точность отрисовки сектора вам необходима?
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
Реализация изложенного выше подхода. И к вопросу о точности результата.
- Вложения
-
- sector2.zip
- (2.37 КБ) 385 скачиваний
-
- miHG141.png (94.3 КБ) 14401 просмотр
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
По построению без диалога:
1. функция ConvexHull();
2. оператор Create Object As ConvexHull
1. функция ConvexHull();
2. оператор Create Object As ConvexHull
-
- Интересующийся
- Сообщения: 39
- Зарегистрирован: 28 янв 2015, 22:07
- Репутация: 1
- Откуда: Воронеж
Re: MapBasic - Нарисовать сектор на карте. Как?
По поводу точности - чтобы глаз не резало при приближении.
При попытки вызвать
где в selection объект дуга и точка центра выдает ошибку:
Для операции оконтуривания требуется минимум 3 узла на входе. Так что красивая идея нарисовать дугу, поставить точку в центре нежизнеспособна. Пока удалось построить сектор, только честно превратив дугу в полилинию, определив координаты концов, нарисовав в них линии, объединив и преобразовав контур объект.
Как объект уже сформированный (сектор) вставить на активную карту?
При попытки вызвать
Код: Выделить всё
Sector = ConvexHull(selection.obj)
Для операции оконтуривания требуется минимум 3 узла на входе. Так что красивая идея нарисовать дугу, поставить точку в центре нежизнеспособна. Пока удалось построить сектор, только честно превратив дугу в полилинию, определив координаты концов, нарисовав в них линии, объединив и преобразовав контур объект.
Как объект уже сформированный (сектор) вставить на активную карту?
Код: Выделить всё
dim Sector as object
Sector = CreateSector(....)
....
? Показать на текущей карте ?
-
- Активный участник
- Сообщения: 160
- Зарегистрирован: 17 янв 2012, 18:51
- Репутация: 74
Re: MapBasic - Нарисовать сектор на карте. Как?
Объедините точку и дугу в один объект (Objects Combine…) и далее
Insert Into таблица ( obj ) Values (ConvexHull(объединенный объект))
Insert Into таблица ( obj ) Values (ConvexHull(объединенный объект))
-
- Активный участник
- Сообщения: 216
- Зарегистрирован: 21 окт 2009, 13:29
- Репутация: 28
- Откуда: Новосибирск
Re: MapBasic - Нарисовать сектор на карте. Как?
При каком приближении? В MapInfo всегда будет существовать приближение, при котором точки дуги и точки приближающей полилинии будут расходиться.tems-ya писал(а):По поводу точности - чтобы глаз не резало при приближении.
Вообще-то, Selection.Obj - это объект, а не группа объектов. Так что ругается правильно. Точку оконтурить нельзя.tems-ya писал(а): При попытки вызватьгде в selection объект дуга и точка центра выдает ошибку:Код: Выделить всё
Sector = ConvexHull(selection.obj)
С чего это? Отличная идея, все работает в два действия.tems-ya писал(а):Так что красивая идея нарисовать дугу, поставить точку в центре нежизнеспособна.
Зачем определять координаты? просто добавляете узел и все.tems-ya писал(а):Пока удалось построить сектор, только честно превратив дугу в полилинию, определив координаты концов, нарисовав в них линии, объединив и преобразовав контур объект.
Объект вставляется не в карту а в таблицу. Если хотите, что бы он был только в окне, тогда вставляйте в косметический слой окна карты(детали в документации), но принцип там тот же.tems-ya писал(а): Как объект уже сформированный (сектор) вставить на активную карту?
- Игорь Белов
- Гуру
- Сообщения: 2229
- Зарегистрирован: 04 янв 2011, 22:00
- Репутация: 1501
- Откуда: Казань
Re: MapBasic - Нарисовать сектор на карте. Как?
tems-ya писал(а):По поводу точности - чтобы глаз не резало при приближении.
Мне одному послышалось «квадратура круга»?Sibit писал(а):При каком приближении? В MapInfo всегда будет существовать приближение, при котором точки дуги и точки приближающей полилинии будут расходиться.
The purpose of computing is insight, not numbers
Кто сейчас на конференции
Сейчас этот форум просматривают: нет зарегистрированных пользователей и 11 гостей