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

Как рассчитать площадь пересечения двух площадных объектов

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

Функция CalcCrossObjectSquare прекрасно рассчитывает площадь пересечения двух площадных объектов.
SquareObject   := CalcCrossObjectSquare(form_main.mvMap.MapHandle, form_main.MapObj2.ObjHandle, form_main.MapObj1.ObjHandle);

Но только в том случаи если в MapObj1 нет подобъектов.
В нашем случаи  MapObj2 пересекает MapObj1 именно в районе подобъекта.
В этом случаи функция, к сожалению, возвращает лишь площадь MapObj2.
На Рис.1 показан вариант, когда площадь пересечения SquareObject вычисляется без проблем.
На Рис.2 показан вариант с подобъектом в MapObj1. Площадь пересечения SquareObject ожидается показанная желтым цветом.
Однако, на Рис.3 показано фактическое значение рассчитанной площади пересечения SquareObject, которое получилось равное всей площади MapObj2.
Что не правильно? Просьба подсказать, какую функцию и как использовать, чтобы получить площадь пересечения как на Рис.2?    
Image1.PNG (42.49 КБ)
 
Функции CalcCrossObjectSquare не знаю и в АПИ ГИС-ядра ее нет. Есть компонент TMapOverlay, который создает пересечения двух площадных объектов с учетом подобъектов.
 
Вы правы, Андрей Владиславович!

Вот функция, которая использовалась, для расчета.
Можно ли в ней учесть подобъект,
или вы рекомендуете использовать компонент TMapOverlay?

function CalcCrossObjectSquare(ExtMap : HMap; baseObj, crossObj : HObj): double;

//------------------------------------------------------------//
// Функция поиска пересечений. Возвращает площадь пересечения //
//------------------------------------------------------------//
function CalcCrossObjectSquare(ExtMap : HMap; baseObj, crossObj : HObj): double;
var cross   : HCross;
   obj     : HObj;
   i       : integer;
   n       : integer;
begin
 cross  := mapCreateObjectsCrossSquare(baseObj, crossObj, 0.001);
 result := 0;
 if Cross=0 then exit;
 obj   := mapCreateSiteObject (ExtMap, ExtMap, KM_IDFLOAT3, 0);
 while mapGetNextCross(cross, obj)<>0 do
 result := result+mapConventionalSquare(obj);
 n := mapPolyCount(obj);
  For i:=1 to n do
  begin
  result := result-mapConventionalSubjectSquare(obj, i);
  end;
 mapFreeObjectsCross(cross);
 mapFreeObject(obj);
end;
 
В Вашей функции площадь полученных подъобъектов вычитается:  result := result-mapConventionalSubjectSquare(obj, i); Зачем?
 
Цитата
Andrey Gheleznyakov написал:
Функции CalcCrossObjectSquare не знаю и в АПИ ГИС-ядра ее нет. Есть компонент TMapOverlay, который создает пересечения двух площадных объектов с учетом подобъектов.
Взял в качестве примера тестовый пример.
И шаблон и обрабатываемый объект ищет хорошо.
Если обрабатываемый объект пересекает край объекта шаблона, то все хорошо. Площадь пересечения вычисляется правильно.
Но если обрабатываемый объект пересекает шаблон в районе его подобъекта, то компонент TMapOverlay не считает, что обрабатываемый объект пересекает шаблон.
Это так и задумано? Но такую программу пользователь не примет.  
Image2.PNG (31.35 КБ)
 
Скорее всего дело в том, что у объекта (подобъектов) контура имеют самопересечения, например, контур одного подобъекта пересекается с другим контуром (объекта, подобъекта). Пришлите фрагмент карты.
 
Цитата
Andrey Gheleznyakov написал:
Скорее всего дело в том, что у объекта (подобъектов) контура имеют самопересечения, например, контур одного подобъекта пересекается с другим контуром (объекта, подобъекта). Пришлите фрагмент карты.
Отправил карту и программу на почту КБ Панорама.
 
На предмет возможной ошибки функцию проверим на своих данных.
 
Проверил определение пересечений на тестовом примере из инсталляции - работает. Для поиска пересечений с учетом подобъектов надо в в качестве шаблона выбирать объект с один контуром (или указывать номер контура), а другой объект уже указывать с подобъектами и в примере надо вызов  ovlObj.SetObjectCross(0, 0.001, 0, ovl_METHOD_SQUARE, ovl_ANYOBJECT); заменить на  ovlObj.SetObjectCross(-1, 0.001, 0, ovl_METHOD_SQUARE, ovl_ANYOBJECT); (первый параметр равен -1).
 
Не совсем все понял.

Первое не понятно,
сделали так:
// res := ovlObj.SetObjectCross(0, 0.001, 0, ovl_METHOD_SQUARE, ovl_ANYOBJECT);
res := ovlObj.SetObjectCross(-1, 0.001, 0, ovl_METHOD_SQUARE, ovl_ANYOBJECT); // Результат тот же, обрабатываемый объект считает, что он просто внутри объекта шаблона, а не пересекает его

Второе не понятно,
рассмотрели это:
res := ovlObj.CreateOVL(1, 0.001, 0, 0);
// третий параметр 0, это означает, что рассматривать в качестве контра шаблона, основной контур, или это не  правильно?

Третье не понятно,
не понятно то, что Вы пишите "...а другой объект уже указывать с подобъектами..."
другой объект, это же обрабатываемый объект. Он без подобъектов изначально. При чем здесь подобъекты?

//==========================================================­===================
// Найти объекты пересечений
//==========================================================­===================
procedure TfrmOvl.btnFindCrossObjClick(Sender: TObject);
var
 res : integer;
 ll, tt : integer;
 SquareObject : double;
begin
 ll := frmOvl.Left + 10;
 tt := frmOvl.Top + btnFindCrossObj.Top + 120;

 temp.Style := OS_NOVIEW;
 objIn.Style := OS_NOVIEW;

 if (edTemplet.Text = EmptyStr) or (edObjIn.Text = EmptyStr)
   then begin
     ShowMessagePos('Выберите на карте шаблон и обрабатываемый объект?', ll, tt);
     exit;
   end;

 frmOvl.MapFind1.Active := false;
 frmOvl.MapFind1.FindPoint := false;
 frmOvl.MapFind1.MapSelect.Clear;
 frmOvl.MapFind1.MapObj.Style := OS_SELECT;
 frmOvl.MapFind1.MapSelect.Excode[-1,OL_SQUARE] := false;
 frmOvl.MapFind1.MapSelect.Excode[10000165,OL_SQUARE] := true;
 frmOvl.MapFind1.Active := true;
 frmOvl.MapFind1.First;

 frmOvl.MapFind1.Center;

 ShowMessage ('найден объект шаблон');

 frmOvl.MapFind2.Active := false;
 frmOvl.MapFind2.FindPoint := false;
 frmOvl.MapFind2.MapSelect.Clear;
 frmOvl.MapFind2.MapObj.Style := OS_SELECT;
 frmOvl.MapFind2.MapSelect.Excode[-1,OL_SQUARE] := false;
 frmOvl.MapFind2.MapSelect.Excode[10000044,OL_SQUARE] := true;
 frmOvl.MapFind2.Active := true;
 frmOvl.MapFind2.First;

 frmOvl.MapFind1.Center;

 ShowMessage ('найден обрабатываемый объект');

 try

     res := ovlObj.CreateOVL(1, 0.001, 0, 0);

     if res = 0
       then begin
         ShowMessagePos('Ошибка создания объекта оверлейных операций!', ll, tt);
         exit;
       end;
                 res := ovlObj.SetObjectCross(-1, 0.001, 0, ovl_METHOD_SQUARE, ovl_ANYOBJECT);

     case res of
       1 : begin
            if mapGetExclusiveSubject(temp.ObjHandle, 0) = 0 // шаблон не замкнут
              then
               ShowMessagePos('Все контура объекта совпадают с шаблоном (лежат на шаблоне)!', ll, tt);
            if mapGetExclusiveSubject(temp.ObjHandle, 0) <> 0 // шаблон замкнут
              then
               ShowMessagePos('Все контура объекта внутри шаблона, либо совпадают!', ll, tt);
           end;
       2 : ShowMessagePos('Все контура объекта вне шаблона!', ll, tt);
       3 : ShowMessagePos('Один или несколько контуров объекта пересекаются с шаблоном!', ll, tt);
       4 : ShowMessagePos('Контур шаблона внутри контура объекта!', ll, tt);
       0 : begin
             ShowMessagePos('Ошибка установки обрабатываемого объекта и метода обработки!', ll, tt);
             exit;
           end;
       end;
     if not (res in [3,4])
       then
          exit;
     while 1=1 do
       begin
           objOut.CreateObjectByKey(1, KM_IDDOUBLE2, objIn.KeyName);

           res := ovlObj.GetNextObject;
           if res = 0
             then
               break;
           objOut.Commit;
           mvMap.Repaint;
           objOut.Style := OS_SELECT;

           SquareObject := objOut.Square;

           ShowMessage ('SquareObject = '+FloatToStr(SquareObject));

           if MessageDlgPos('Вычислить следующее пересечение?',mtConfirmation, mbOKCancel, 0, ll, tt) = IDCANCEL
           then begin        // если нажата кнопка Отмена, то
             ObjOut.Delete;  // удалить созданный рез. объект
             exit;           // и на выход...
           end;

          ObjOut.Delete; // если нажата кнопка Ок, то просто удалить
                        // объект и в начало цикла ...
       end;

     // если пересечений больше нет, то выдать сообщение и на выход
     ShowMessagePos('Пересечений больше нет!', ll, tt);
 finally
   ovlObj.FreeOVL;
 end;
end;
Изменено: Сергей Викторович - 01.02.2021 12:52:44
Страницы: 1 2 3 4 5 След.
Читают тему (гостей: 1)



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

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