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

Пересечение объектов

Поиск  Пользователи  Правила  Войти
Форум » Настольные приложения » GIS ToolKit, GIS ToolKit Active, ГИС Конструктор для Windows
Страницы: 1
RSS
Пересечение объектов, Пересечение сложных объектов
 
Доброе время суток.

Я ищу пересечения разных объектов замкнутых с замкнутыми, линий проходящих через замкнутые объекты.
На сложных объектах (с вложенными контурами) некорректно находятся пересечения.
Может я использую неверные функции:
Использую для поиска пересечений:
- вычисляется количество пересечений mapCreateObjectsCross,
- потом выделяются контура пересечений mapGetNextCross в цикле

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

Боюсь предсказать, что будет если оба объекта будут с вложенными контурами?!!!

Версия "GIS ToolKit" v.14.3.2.0 - может в новой версии это все работает корректно (хотелось попробовать перед тем как покупать)?  
 
Добрый день!

Цитата
Александр Коновалов написал:
Версия "GIS ToolKit" v.14.3.2.0 - может в новой версии это все работает корректно (хотелось попробовать перед тем как покупать)?  

Актуальные полнофункциональные версии продуктов всегда доступны на нашем сайте в разделе Скачать.
Условия использования программного обеспечения для ознакомления (без приобретения лицензии) указаны тут.

Функция mapCreateObjectsCross должна корректно работать в том числе с площадными объектами, имеющими внутренние контура, и/или являющимися мультиполигонами.
Обратите внимание, что на обработку влияет параметр method и значение FLAGINSIDEOBJECTS в его составе, а также какой объект из какого "вырезается".

Код
//------------------------------------------------------------------
// Пересечение двух объектов - нахождение общей части объектов,
// один из которых (ПЕРВЫЙ объект карты) - РЕЗАК(по которому режут)
// другой (ВТОРОЙ объект карты) - ОБ ЕКТ, КОТОРЫЙ РЕЖУТ.
// Только для ПЛОЩАДНЫХ или ЛИНЕЙНЫХ объектов
// info1 - первый объект карты - РЕЗАК (произвольный контур без подобъектов)
// info2 - второй объект карты (произвольный линейный или площадной объект с подобъектами)
// method - тип результирующих объектов
//          LOCAL_SQUARE - площадной, LOCAL_LINE - линейный
//          тип результирующих объектов зависит от типа второго объекта:
//          - если второй объект незамкнутый, то тип только LOCAL_LINE,
//          - если второй объект замкнутый, то тип может быть LOCAL_LINE или LOCAL_SQUARE.
// При логическом сложении method и флага проверки входимости (FLAGINSIDEOBJECTS = 32
// см. maptype.h) в класс пересечения будут добавлены объекты, которые полностью входят
// в объект - РЕЗАК  (напр. LOCAL_SQUARE | FLAGINSIDEOBJECTS)
// precision - точность при дотягивании (в метрах)
// При отсутствии пересечения или при ошибке возвращает ноль
//------------------------------------------------------------------
_MAPIMP HCROSS _MAPAPI mapCreateObjectsCross(HOBJ info1, HOBJ info2, long int method, double precision)


Если некорректное поведение продолжится, то потребуется больше конкретики. Как минимум потребуется взглянуть на пример кода, на котором это наблюдается.
 
 

Первоначальные контура 1) замкнутый контур (типа баранки) и  линейный объект. В результате нахождения пересечения получается линейный контур (черным цветом), состоящий из двух кусочков (правильно - должно было быть три куска линейных объектов).
Изменено: Александр Коновалов - 18.08.2025 15:25:50
 
Привожу код:
myHCROSS:=mapCreateObjectsCross(MapObj1.ObjHandle, MapObj2.ObjHandle,32,0);
If myHCROSS>0 then begin
  hSite := mapGetSiteIdent(mvMap.MapHandle,1);
  hObjKPT := mapCreateSiteObject(mvMap.MapHandle, hSite,KM_IDDOUBLE2, 0);
  mapRegisterObject(hObjKPT, 10000609, OL_LINE);
  mapCreateSubject(hObjKPT);
   While mapGetNextCross(myHCROSS,hObjKPT)>0 do
   begin
   mapCommitObject(hObjKPT);
   mapFreeObject(hObjKPT);
   
   hSite := mapGetSiteIdent(mvMap.MapHandle,1);
   hObjKPT := mapCreateSiteObject(mvMap.MapHandle, hSite,KM_IDDOUBLE2, 0);
   mapRegisterObject(hObjKPT, 10000609, OL_LINE);
   mapCreateSubject(hObjKPT);
   end;
mapFreeObject(hObjKPT);
end;
mapFreeObjectsCross(myHCROSS);
Изменено: Александр Коновалов - 18.08.2025 14:55:55
 
вот файлы картинки
Начало.png (28.61 КБ)
 
Добрый день!
Судя по описанию функции mapCreateObjectsCross, если первый объект (резак) - красный, то решение верно.
В описании написано:
// info1 - первый объект карты - РЕЗАК (произвольный контур без подобъектов)
Это значит, что подобъект (дырка) при разрезании не используется).

Есть продвинутый набор функций, поддерживающий более сложные резаки (шаблоны) - см. crossapi.h:
ovlCreate
ovlSetTemplet
ovlSetObjectCross
ovlGetNextObject
ovlFree

Пример:
Код
  // Создать пустой объект для записи шаблона для обрезки объектов
  HOBJ templet = mapCreateSiteObject(hmap, hsite, IDDOUBLE2, 0);

  // Создать пустой объект для записи обрабатываемого объекта
  HOBJ object = mapCreateSiteObject(hmap, hsite, IDDOUBLE2, 0);

  // Создать пустой объект для записи результата
  // (для записи результата рекомендуется тип IDDOUBLE2 или IDDOUBLE3)
  HOBJ objectpart = mapCreateSiteObject(hmap, hsite, IDDOUBLE2, 0);

  // Запросить объект карты
  mapReadObjectByNumber(hmap, hsite, templet, 1, templetnumber);

  // Запросить объект карты
  mapReadObjectByNumber(hmap, hsite, object, 1, objectnumber);

  // Установить тип результирующего объекта равным типу обрабатываемого
  mapDescribeObject(objectpart, mapObjectCode(object));

  // Создать объект оверлейных операций
  HOVL hovl = ovlCreate(hmap, 1, DOUBLENULL);

  if (hovl == 0)
  {
    // Ошибка создания объекта оверлейных операций
  }
  else
  {
    // Установить шаблон для оверлейных операций
    // (по основному контуру объекта, с согласованием контура
    //  шаблона с обрабатываемыми объектами)
    int res = ovlSetTemplet(hovl, templet, 0, 1);

    if (res == 0)
    {
      // Запросить код ошибки
      if (ovlGetErrorCode(hovl) != 0)
      {
        // Запросить описание ошибки для вывода в окно или записи в журнал
        ::MessageBox(0, ovlGetError(hovl), "", MB_OK);
      }
    }
    else
    {
      int errorcode = 0;

      // Установить обрабатываемый объект и метод обработки
      // (все контура, результат - все линейные контура)
      int location = ovlSetObjectCross(hovl, object, -1, 0.0, 0, METHOD_LINE, 0);

      // Расположение объекта относительно шаблона
      if (location == 0)
      {
        // Запросить код ошибки
        if (ovlGetErrorCode(hovl) != 0)
        {
          // Запросить описание ошибки
          ::MessageBox(0, ovlGetError(hovl), "", MB_OK);
        }
      }
      else if (location == 1)
      {
        // Объект внутри шаблона
        // ...
      }
      else if (location == 2)
      {
        // Объект вне шаблона
        // ...
      }
      else  // location == 3 или 4 (Объект пересекается с шаблоном)
      {
        int side;

        while(1)
        {
          // Запросить очередную часть разрезаемого объекта
          side = ovlGetNextObject(hovl, objectpart);

          if (side == 0)
          {
            // Запросить код ошибки
            if (ovlGetErrorCode(hovl) != 0)
            {
              // Запросить описание ошибки
              ::MessageBox(0, ovlGetError(hovl), "", MB_OK);
              break;
            }

            // Запросить метрику основного контура шаблона, согласованного
            // с частями разрезаемого объекта
            if (ovlGetAdjustTemplet(hovl, templet, 0))
            {
              // Сохранить объект, если контур шаблона обновился
              mapCommitObject(templet);
            }
            else
            {
              // Запросить код ошибки
              if (ovlGetErrorCode(hovl) != 0)
              {
                // Запросить описание ошибки
                ::MessageBox(0, ovlGetError(hovl), "", MB_OK);
              }
            }

            // Поиск частей разрезаемого объекта закончен
            break;
          }

          // Установить разные коды объектов для результирующих объектов
          if (side == 1)
          {
            // Объект, находящийся внутри шаблона
            mapRegisterObjectByKey(objectpart, "L1000000008");
          }
          else
          {
            // Объект, находящийся вне шаблона
            mapRegisterObjectByKey(objectpart, "L1000000007");
          }

          // Сохранить объект objectpart
          mapCommitObjectAsNew(objectpart);
        }
      }
    }

    // Освободить объект оверлейных операций
    ovlFree(hovl);
  }

  // Освободить объекты
  mapFreeObject(objectpart);
  mapFreeObject(object);
  mapFreeObject(templet);
 
Добрый день!

Вы продолжаете использовать 14-ю версию или это наблюдается в актуальной версии?
Актуальная на текущий момент версия 15.1.5.0.

Для начала немного наведем порядок в Вашем коде:
Цитата

myHCROSS:=mapCreateObjectsCross(MapObj1.ObjHandle, MapObj2.ObjHandle, 32, 0);
If myHCROSS <> 0 then
begin
 hSite := mapGetSiteIdent(mvMap.MapHandle,1);
 hObjKPT := mapCreateSiteObject(mvMap.MapHandle, hSite, KM_IDDOUBLE2, 0);

 If hObjKPT <> 0 then
 begin

   mapRegisterObject(hObjKPT, 10000609, OL_LINE);
   mapCreateSubject(hObjKPT); // Лишнее. Зачем создавать пустой подобъект?

   While mapGetNextCross(myHCROSS, hObjKPT)>0 do
   begin
      mapCommitObjectAsNew(hObjKPT); // Сохранить новый объект на карте
   
      // Ниже - лишние действия. Экземпляр класса работы с объектом пересоздавать не надо!
      mapFreeObject(hObjKPT);
      hSite := mapGetSiteIdent(mvMap.MapHandle,1);
      hObjKPT := mapCreateSiteObject(mvMap.MapHandle, hSite,KM_IDDOUBLE2, 0);
      mapRegisterObject(hObjKPT, 10000609, OL_LINE);
      mapCreateSubject(hObjKPT);

   end;

   mapFreeObject(hObjKPT);
 end;
 mapFreeObjectsCross(myHCROSS);

end;
mapFreeObjectsCross(myHCROSS);

Получим такой вариант:
Код
myHCROSS:=mapCreateObjectsCross(MapObj1.ObjHandle, MapObj2.ObjHandle, 32, 0);

If myHCROSS <> 0 then
begin
 hSite := mapGetSiteIdent(mvMap.MapHandle,1);
 hObjKPT := mapCreateSiteObject(mvMap.MapHandle, hSite, KM_IDDOUBLE2, 0);

 If hObjKPT <> 0 then
 begin
   mapRegisterObject(hObjKPT, 10000609, OL_LINE);

   While mapGetNextCross(myHCROSS, hObjKPT)>0 do
   begin
      mapCommitObjectAsNew(hObjKPT); // Сохранить новый объект на карте
   end;

   mapFreeObject(hObjKPT);
 end;
 mapFreeObjectsCross(myHCROSS);
end;


Но правильнее использовать новый функции резки объектов, как было сказано выше:

Цитата
Александр Кружков написал:
Есть продвинутый набор функций, поддерживающий более сложные резаки (шаблоны) - см. crossapi.h:
Страницы: 1
Читают тему (гостей: 1)



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

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