На главную... Продукты | Технологии | Классификаторы | Проекты | Скачать | Цены| Форум | Статьи | Обучение | Контакты

Очень долгий mapSelectSeekArea

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: 1
RSS
Очень долгий mapSelectSeekArea
 
Здравствуйте, попробовал реализовать поиск, пересекаемых маршрутом, линейных объектов.
Код
procedure AppendExCodeToSelect(MapHandle: HMap; sel: HSelect; exCode: Integer; aLocals: TLOCALS = []);
var
  l: TLOCAL;
  ii: Integer;
  iIncode : Integer;
  _rsc: HRsc;
begin
  _rsc := mapgetRscIdent(MapHandle, 0);

  if aLocals = [] then
    aLocals := [L_LINE, L_SQUARE, L_MARK, L_TEXT, L_VECTOR, L_PATTERN];

  for l in aLocals do
    for ii := 1 to mapGetRscObjectsCount(_rsc, exCode, ord(l)) do
      begin
        iIncode := mapGetRscObjectCodeByNumber(_rsc, exCode, ord(l), ii);
        mapSelectObject(sel, iIncode, 1);
      end;

end;


function FindCrossLineObjects(CurrMapObject: TMapObj): String;
var
  HS : HSelect;
  Finding: TMapObj;
  ZoneR: integer;
  exCode: integer;
  ZoneObj : HObj;
begin
  Result := '';
   exCode := 31410000;
   
  ZoneR:= 1;
  ZoneObj := mapCreateCopyObject(MapScreen.MapHandle, CurrMapObject.ObjHandle);
  Finding:= TMapObj.Create(nil);
  HS := mapCreateMapSelectContext(MapScreen.MapHandle);
  try
    Finding.MapView := MapScreen;
    Finding.PlaceOut := PP_PLANE;
    // Построить зону 
    if mapZoneObjectEx(ZoneR, ZoneObj, 0, 1, ZoneR/10, 3, 3) > 0 then
    begin //найти объекты в зоне
      // чистим все условия
      mapClearSelectContext(HS);
      // отменяем доступ ко всем
      mapSelectObject(HS, -1, 0);
      //добавим к селекту коды
      AppendExCodeToSelect(MapScreen.MapHandle, HS, exCode);
      //добавим к селекту область поиска
      mapSelectSeekArea(HS, ZoneObj, 0, 1);
      //запускаем поиск по условиям селекта
      if mapSeekSelectObject(MapScreen.MapHandle, Finding.ObjHandle, HS, cWO_FIRST) <> 0 then
      begin
        //обработка найденного
   //...
        //ищем дальше
        while mapSeekSelectObject(MapScreen.MapHandle, Finding.ObjHandle, HS, cWO_NEXT) <> 0 do
          begin
            //обработка найденного
            //...
          end;
      end;
    end;
      
    Result := '...'
  finally
   if ZoneObj <> 0
     then mapFreeObject(ZoneObj);
    Finding.Free;
    mapDeleteSelectContext(HS);
  end;
end;
Алгоритм работает, НО!

За маршрут взял "непротяженную" 15 км дорогу, объектов интереса - около 10
 объекты интереса - мосты. Отрабатывает менее секунды.
 объекты интереса - реки. Отрабатывает почти секунду.

За маршрут взял "протяженную" 400 км дорогу, объектов интереса - около 20
 объекты интереса - мосты. Отрабатывает почти секунду.
 объекты интереса - реки. Отрабатывает 50 секунд.
 объекты интереса - горизонтали (10 штук) 75 секунд.

т.е. получается поиск пересечения очень сильно зависит от длины объектов!
Причем меня-то интересовал пока только факт пересечения (т.е. номера объектов).

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

При поиске пересечения зоны с векторным объектом (мостом) проверяется всего 1 отрезок.
При поиске пересечения зоны с незамкнутой горизонталью проверяется N-1 отрезок, где N - число точек горизонтали. В среднем случае пересечение с объектом может быть обнаружено при проходе (по отрезкам) до середины горизонтали. Вероятно средняя скорость обработки будет ниже в N/2 раз (по сравнению с векторным объектом).

P.S. Не для Вашей функции, но вдруг поможет: в случае многократного прохода по отобранным объектам может помочь последний параметр функции (action = 1):  mapSelectSeekArea(HS, ZoneObj, 0, 1, 1, 0, 1);
см. описание функции:

 // action   - порядок поиска объектов :
 //            0 - последовательный поиск по мере запроса объектов,
 //            1 - предварительный отбор всех объектов,
 //            ускоряет многократный запрос отобранных объектов;
 
Цитата
Александр Кружков написал:
mapSelectSeekArea(HS, ZoneObj, 0, 1, 1, 0, 1);
Спасибо, стало чуть лучше 67сек вместо 71сек
 
Для этой задачи алгоритм оказался избыточным!!!
Расчет зоны и включение ее в селект оказалось ОГРОМНЫМ злом.
На эту мысль навела информация
Цитата
Александр Кружков написал:
проверяется N-1 отрезок
Т.е. для установления факта пересечения похоже пересчитываются (все отрезки всех рек * все отрезки маршрута)
Убрал из алгоритма все связанное с зоной, добавил вместо этого выборку по габаритной рамке маршрута
Код
mapObjectFrame(CurrMapObject.ObjHandle, frame);
mapSelectSeekAreaFrame(HS, frame, 0, 1);
Итог:
Маршрут 425 км,
объектов в выборке 2057 (линейная и площадная гидрография),  
точек пересечения 1386
Время работы алгоритма вместе с поиском точек пересечения - 1,3 сек
Изменено: Dmitry Stasev - 13.02.2019 07:46:38
 
Абсолютно с Вами согласен. Рад, что Вы нашли более рациональное решение.

P.S. Любая задача решается множеством способов, выбор которого ограничен лишь Вашей фантазией.
Страницы: 1
Читают тему (гостей: 1)



© КБ Панорама, 1991-2024

Регистрируясь или авторизуясь на форуме, Вы соглашаетесь с Политикой конфиденциальности