Идентификация точечных объектов

0 голосов
спросил 05 Фев, 07 от Voltron (2,800 баллов) в категории Программные продукты Esri
Написал на VBA программку для идентификации объектов выделенного слоя (использовал примеры из EDN и Exploring ArcObjects). Но почему-то она не работает с точечными объектами. Может кто подскажет в чем причина.
Вот код

 Set pMxApp = Application
 Set pDoc = Application.Document
 
 If pDoc.SelectedLayer Is Nothing Then Exit Sub
 Set pIdentify = pDoc.SelectedLayer
 Set pPoint = pMxApp.Display.DisplayTransformation.ToMapPoint(X, Y)
 Set pIDArray = pIdentify.Identify(pPoint)
 
 If Not pIDArray Is Nothing Then
  Set pFeatIdObj = pIDArray.Element(0)
  Set pIdObj = pFeatIdObj
  pIdObj.Flash pMxApp.Display
 Else
 .....
End If

10 Ответы

0 голосов
ответил 05 Фев, 07 от Scok (1,260 баллов)
В следующий раз пиши, что именно не работает и свои предположения.

К сожалению, с интерфейсом IIdentify не разбирался, хотя полезная штука. А вот с флешем основных геометрий немного кода ниже...
0 голосов
ответил 05 Фев, 07 от Scok (1,260 баллов)
//=== I === подсветка геометрии на карте ==========================================================
long <класс>::FlashGeometry(IGeometry *ipGeom,int FlashCount)
{
long RetCode;
ESRI::ArcGIS::Geodatabase::IFeatureClass *ipFC;
ESRI::ArcGIS::Geodatabase::IFeature *ipF;
ESRI::ArcGIS::Geometry::IGeometry *ipG;
ESRI::ArcGIS::Geometry::esriGeometryType GeomType;

if(m_ipFL == 0) return 100003;               // проверка на наличие Shape-файла
if(FlashCount < 0) 100012;                    // проверка на корреткное значение FlashCount

ipFC = m_ipFL->get_FeatureClass();          // получение из слоя Feature-класса

// поиск идентичной геометрии
RetCode = mmFindGeometry(ipFC,ipGeom,&ipF);
if(RetCode != 0) return RetCode;

// получение геометрии и определение ее формы
ipG = ipF->get_Shape();
GeomType = ipG->get_GeometryType();

// в зависимости от типа геомерии вызов различных методов подсветки
switch(GeomType)
     {
      case esriGeometryPolygon: mmFlashPolygon(ipF,FlashCount);break;
      case esriGeometryPolyline: mmFlashLine(ipF,FlashCount);break;
      case esriGeometryLine: mmFlashLine(ipF,FlashCount);break;
      case esriGeometryPoint: mmFlashPoint(ipF,FlashCount);break;
      case esriGeometryMultipoint: mmFlashPoint(ipF,FlashCount);break;
      default: return 100011;
     }

return 0;
}
0 голосов
ответил 05 Фев, 07 от Scok (1,260 баллов)
//=== S === отрисовка полигона ====================================================================
long <класс>::mmFlashPolygon(IFeature *ipF,int FlashCount)
{
int i;
ESRI::ArcGIS::Display::IScreenDisplay *ipDisplay;
ESRI::ArcGIS::Display::ISimpleFillSymbol *ipSFSym;
ESRI::ArcGIS::Display::ISymbol *ipSym;
ESRI::ArcGIS::Display::IRgbColor *ipRGB_Color;

ipDisplay = (m_ipMxDoc->get_ActivatedView())->get_ScreenDisplay();

ipSFSym = new ESRI::ArcGIS::Display::SimpleFillSymbolClass();
ipRGB_Color = new ESRI::ArcGIS::Display::RgbColorClass();

ipSFSym->Outline = 0;
ipRGB_Color->set_Green(128);
ipSym = dynamic_cast<ESRI::ArcGIS::Display::ISymbol*>(ipSFSym);
ipSym->set_ROP2(ESRI::ArcGIS::Display::esriRasterOpCode::esriROPNotXOrPen);

ipDisplay->StartDrawing(0,ESRI::ArcGIS::Display::esriScreenCache::esriNoScreenCache);

ipDisplay->SetSymbol(ipSym);

for(i=0;i<FlashCount;i++)          // цикл мерцаний
     {
      ipDisplay->DrawPolygon(ipF->get_Shape());     // первая подсветка
      System::Threading::Thread::Sleep(300);
      ipDisplay->DrawPolygon(ipF->get_Shape());     // убрать первую подсветку
      System::Threading::Thread::Sleep(300);
     }
ipDisplay->DrawPolygon(ipF->get_Shape());     // вторая подсветка

ipDisplay->FinishDrawing();

return 0;
}
0 голосов
ответил 05 Фев, 07 от Scok (1,260 баллов)
//=== S === отрисовка линии =======================================================================
long <класс>::mmFlashLine(IFeature *ipF,int FlashCount)
{
int i;
ESRI::ArcGIS::Display::IScreenDisplay *ipDisplay;
ESRI::ArcGIS::Display::ISimpleLineSymbol *ipSLSym;
ESRI::ArcGIS::Display::ISymbol *ipSym;
ESRI::ArcGIS::Display::IRgbColor *ipRGB_Color;

ipDisplay = (m_ipMxDoc->get_ActivatedView())->get_ScreenDisplay();

ipSLSym = new ESRI::ArcGIS::Display::SimpleLineSymbolClass();
ipRGB_Color = new ESRI::ArcGIS::Display::RgbColorClass();

ipSLSym->set_Width(4);
ipRGB_Color->set_Green(128);
ipSym = dynamic_cast<ESRI::ArcGIS::Display::ISymbol*>(ipSLSym);
ipSym->set_ROP2(ESRI::ArcGIS::Display::esriROPNotXOrPen);

ipDisplay->StartDrawing(0,ESRI::ArcGIS::Display::esriScreenCache::esriNoScreenCache);

ipDisplay->SetSymbol(ipSym);
for(i=0;i<FlashCount;i++)          // цикл мерцаний
     {
      ipDisplay->DrawPolyline(ipF->get_Shape());     // первая подсветка
      System::Threading::Thread::Sleep(300);
      ipDisplay->DrawPolyline(ipF->get_Shape());     // убрать первую подсветку
      System::Threading::Thread::Sleep(300);
     }
ipDisplay->DrawPolyline(ipF->get_Shape());     // вторая подсветка

ipDisplay->FinishDrawing();

return 0;
}
0 голосов
ответил 05 Фев, 07 от Scok (1,260 баллов)
//=== S === отрисовка точки =======================================================================
long <класс>::mmFlashPoint(IFeature *ipF,int FlashCount)
{
int i;
ESRI::ArcGIS::Display::IScreenDisplay *ipDisplay;
ESRI::ArcGIS::Display::ISimpleMarkerSymbol *ipSMSym;
ESRI::ArcGIS::Display::ISymbol *ipSym;
ESRI::ArcGIS::Display::IRgbColor *ipRGB_Color;
ESRI::ArcGIS::Geometry::IGeometry *ipG;
ESRI::ArcGIS::Geometry::esriGeometryType GeomType;

ipDisplay = (m_ipMxDoc->get_ActivatedView())->get_ScreenDisplay();

ipSMSym = new ESRI::ArcGIS::Display::SimpleMarkerSymbolClass();
ipRGB_Color = new ESRI::ArcGIS::Display::RgbColorClass();

ipSMSym->set_Style(ESRI::ArcGIS::Display::esriSimpleMarkerStyle::esriSMSCircle);
ipRGB_Color->set_Green(128);
ipSym = dynamic_cast<ESRI::ArcGIS::Display::ISymbol*>(ipSMSym);
ipSym->set_ROP2(ESRI::ArcGIS::Display::esriROPNotXOrPen);

// получение типа геометрии и проверка на точку или мультиточку
// в зависимости от типа точки ее мерцание методом DrawPoint(...) или DrawMultipoint(...)
ipG = ipF->get_Shape();
GeomType = ipG->get_GeometryType();

ipDisplay->StartDrawing(0,ESRI::ArcGIS::Display::esriScreenCache::esriNoScreenCache);
ipDisplay->SetSymbol(ipSym);

if(GeomType == ESRI::ArcGIS::Geometry::esriGeometryType::esriGeometryPoint)     // отображение точки
     {
      for(i=0;i<FlashCount;i++)          // цикл мерцаний
          {
           ipDisplay->DrawPoint(ipF->get_Shape());     // первая подсветка
           System::Threading::Thread::Sleep(300);
           ipDisplay->DrawPoint(ipF->get_Shape());     // убрать первую подсветку
           System::Threading::Thread::Sleep(300);
          }
      ipDisplay->DrawPoint(ipF->get_Shape());     // вторая подсветка
     }
else          // отображение мультиточки
     {
      for(i=0;i<FlashCount;i++)          // цикл мерцаний
          {
           ipDisplay->DrawMultipoint(ipF->get_Shape());     // первая подсветка
           System::Threading::Thread::Sleep(300);
           ipDisplay->DrawMultipoint(ipF->get_Shape());     // убрать первую подсветку
           System::Threading::Thread::Sleep(300);
          }
      ipDisplay->DrawMultipoint(ipF->get_Shape());     // вторая подсветка
     }

ipDisplay->FinishDrawing();

return 0;
}
0 голосов
ответил 06 Фев, 07 от Voltron (2,800 баллов)
Не срабатывает идентификация для объектов типа точка. Т.е. при выборе инструмента идентификации и последующем клике на точечный объект ничего не происходит :-(. А вот полигональные и линейные объекты обрабатываются нормально -- возвращается значение ключевого поля.
В чем траблы понять не могу. Стандартный инструмент работает одинаково как с точечными, так и с полигональными объектами.
За примеры подсветки -- спасибо. Может пригодится
0 голосов
ответил 06 Фев, 07 от sschainik (4,900 баллов)
Идентификация в коде производится с использованием точки:
Set pIDArray = pIdentify.Identify(pPoint)

в этом случае для идентификации точки надо точно попасть курсором по идентифицируемой точке, что проблематично.
Возможно для идентификации лучше использовать "область", зависящую от масштаба. Я применяю следующее:
Dim searchDist as Double
Dim pSrchEnv As IEnvelope
Set pSrchEnv = MapControl1.ActiveView.Extent.Envelope
searchDist = MapControl1.Map.MapScale / 750
pSrchEnv.Width = searchDist
pSrchEnv.Height = searchDist
pSrchEnv.CenterAt pPoint
Set pIDArray = pIdentify.Identify(pSrchEnv)

можно жестко прописать дистанцию идентификаци, кроме того в моем примере не учитывается метрическая система (метры, дециметры или ....), которая трансфрормируется с помощью IUnitConverter
0 голосов
ответил 07 Фев, 07 от Voltron (2,800 баллов)
Спасибо, помогло :-). Но т.к. объекты типа MapControl у меня недоступны, то немного переделал код. Вот, может кому еще пригодится:

 Dim searchDist As Double
 Dim pSrchEnv As IEnvelope
 Set pSrchEnv = pDoc.ActiveView.Extent.Envelope
 searchDist = pMap.MapScale / 750
 pSrchEnv.Width = searchDist
 pSrchEnv.Height = searchDist
 Set pPoint = pMxApp.Display.DisplayTransformation.ToMapPoint(X, Y)
 pSrchEnv.CenterAt pPoint
 Set pIdentify = pDoc.SelectedLayer
 Set pIDArray = pIdentify.Identify(pSrchEnv)
0 голосов
ответил 02 Март, 07 от Edward (180 баллов)

подскажите как бороться с тем, что при езменении масштаба(уменьшении) и даже после возврата к предыдущему(где она работала), идентификация перестает работать, выдает ошибку "Run-time error 91" - Object variable or With block variable not set.

0 голосов
ответил 18 Июль, 07 от Irochka (900 баллов)
при идентификации объекта в окне результата идентификации можно увидеть и атрибутивные данные и соответствующие данные со связанной базы.
 
Одной записи в атрибутивке соответствует несколько записей в базе.
 
Нельзя ли вывести их в этом окне сортированными и высвечивать только те поля которые отмечены галочкой в свойствах связанной базы????
Добро пожаловать на сайт Вопросов и Ответов, где вы можете задавать вопросы по GIS тематике и получать ответы от других членов сообщества.
...